#include <iostream>
#include <cstring>
#include <cerrno>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char* args[])
{
    if(argc != 2)
    {
        std::cout << "Usage: \n";
        std::cout << args[0] << " port\n";
        return 0;
    }
    uint16_t port = std::stoi(args[1]);
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if(listenfd < 0)
    {
        std::cout << "socket failed, errno : " << strerror(errno) << std::endl;
        return 0;
    }
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(port); // 注意字节序在转换时，函数要用对，port是一个16字节的数，要用 htons 函数
    server.sin_addr.s_addr = INADDR_ANY; // 接收任意ip地址发来的请求
    int n = bind(listenfd, (struct sockaddr*)&server, sizeof(server)); // 要手动绑定，因为服务器的端口号必须时固定的，被别人所知道的，不能是随机的
    
    if(listen(listenfd, 10) < 0)
    {
        std::cout << "listen failed, errno : " << strerror(errno) << std::endl;
        return 0;
    }
    struct sockaddr_in client;
    memset(&client, 0, sizeof(client));
    socklen_t sz = sizeof(client);
    int sockfd = accept(listenfd, (struct sockaddr*)&client, &sz);
    if(sockfd < 0)
    {
        std::cout << "accept failed, errno : " << strerror(errno) << std::endl;
        return 0;
    }

    char buffer[1024];
    while(1)
    {
        struct sockaddr_in tmp;
        socklen_t sz = sizeof(tmp);
        int n = recv(sockfd, buffer, sizeof(buffer) - 1, 0);
        if(n > 0)
        {
            buffer[n] = 0;
            std::cout << "client # " << buffer << std::endl;
        }
        else if(n == 0)
        {
            std::cout << "退出" << std::endl;
            break;
        }
        else
        {
            std::cout << "recvfrom failed, error: " << strerror(errno) << std::endl;
            break;
        }

        std::string message = buffer;
        message += " 收到";
        n = send(sockfd, message.c_str(), message.size(), 0);
        if(n < 0)
        {
            std::cout << "sendto failed, error: " << strerror(errno) << std::endl;
            break;
        }
    }
    return 0;
}
